﻿//     Copyright (c) Microsoft Corporation.  All rights reserved.

using System;
using System.Collections.Generic;
using System.Data.Entity;
using System.Linq;
using System.Threading.Tasks;
using System.Web.Mvc;
using Gateway.Console.Models;
using Gateway.Console.Services;
using Gateway.Console.Services.Azure;

namespace Gateway.Console.Controllers
{
    public class AnalyticsController : OAuthAccessController
    {
        public AnalyticsController() 
            : base("Analytics", new [] { ResourceSelectors.RDFE })
        {

        }

        public async Task<ActionResult> Index()
        {
            return await DoWithAccessAsync("Index", null, async () =>
            {
                var model = await _db.AnalyticsModel
                    .ToListAsync();
                var item = model.FirstOrDefault();
                if (item == null)
                {
                    item = CreateModel();
                }
                else
                {
                    item.ClusterNameToCreate = item.ClusterName;
                }
                await AugmentModel(_db, item);
                return View(item);
            });
        }

        [HttpPost]
        public async Task<ActionResult> CreateAnalytics(AnalyticsModel analytics)
        {
            if (ModelState.IsValid)
            {
                var accessToken = Session.GetAccessToken(ResourceSelectors.RDFE);
                bool createCluster = analytics.EnableAnalytics && analytics.ClusterName == AnalyticsModel.CreateClusterTag;
                bool destroyCluster = false;
                if (createCluster)
                {
                    analytics.ClusterName = analytics.ClusterNameToCreate;
                }
                analytics.RefreshToken = accessToken.RefreshToken;
                if (analytics.Id == 0)
                {
                    _db.AnalyticsModel.Add(analytics);
                }
                else
                {
                    destroyCluster = !analytics.EnableAnalytics;

                    var currentModel = await _db.AnalyticsModel.FindAsync(analytics.Id);
                    currentModel.EnableAnalytics = analytics.EnableAnalytics;
                    if (!destroyCluster)
                    {
                        currentModel.ClusterName = analytics.ClusterName;
                        currentModel.ClusterUserName = analytics.ClusterUserName;
                        currentModel.ClusterPassword = analytics.ClusterPassword;
                        currentModel.ClusterNodeCount = analytics.ClusterNodeCount;
                        currentModel.RefreshToken = analytics.RefreshToken;
                    }

                    _db.AnalyticsStatus.RemoveRange(currentModel.StatusMessages);
                    _db.Entry(currentModel).State = EntityState.Modified;
                    analytics = currentModel;
                }
                await _db.SaveChangesAsync();
                await AugmentModel(_db, analytics);
                analytics.AnalyticsServerHost = Request.Url.GetComponents(UriComponents.SchemeAndServer, UriFormat.SafeUnescaped);
                var deployment = await _db.Deployments.FirstOrDefaultAsync();
                if (createCluster)
                {
                    AzureManagement.CreateAnalytics(analytics, accessToken, deployment.SubscriptionSelection);
                }
                else if (destroyCluster)
                {
                    AzureManagement.DeleteAnalytics(analytics, accessToken, deployment.SubscriptionSelection);
                }
                else if (analytics.EnableAnalytics)
                {
                    AzureManagement.UpdateAnalytics(analytics, accessToken, deployment.SubscriptionSelection);
                }
            }
            return Json(analytics.Id);
        }      

        private AnalyticsModel CreateModel()
        {
            return new AnalyticsModel
            {
                EnableAnalytics = false,
                CreateCluster = true,
                ClusterNameToCreate = "MyAppAnalytics",
                ClusterNodeCount = 4,
            };
        }

        private async Task AugmentModel(ConsoleContext db, AnalyticsModel model)
        {
            var deployment = await db.Deployments.FirstOrDefaultAsync();
            model.Disabled = deployment == null;
            model.AvailableClusters = await GetClusterSelectListAsync(deployment);
            model.Reports = await db.AnalyticsReportModels.ToListAsync();
        }

        private async Task<IEnumerable<Tuple<string, string>>> GetClusterSelectListAsync(Deployment deployment)
        {
            if (deployment != null)
            {
                using (var hdInsightClient = new HDInsightManagement(Session.GetAccessToken(ResourceSelectors.RDFE), deployment.SubscriptionSelection, String.Empty))
                {
                    IEnumerable<Tuple<string, string>> retval = new List<Tuple<string, string>> 
                    {
                        Tuple.Create(AnalyticsModel.CreateClusterTag, "Create New HDInsight Cluster"),
                        Tuple.Create(AnalyticsModel.DividerTag,       "----------------------------"),
                    };
                    try
                    {
                        var clusters = await hdInsightClient.ListHDInsightClustersAsync();
                        retval = retval.Concat(clusters.Select(cluster => Tuple.Create(cluster, cluster)));
                    }
                    catch
                    {
                    }
                    return retval;
                }
            }
            else
            {
                return new Tuple<string, string>[0];
            }
        }

        [HttpGet]
        public async Task<ActionResult> CheckClusterNameAvailable(AnalyticsModel model)
        {
            if (model.ClusterName != AnalyticsModel.CreateClusterTag)
            {
                return Json(true, JsonRequestBehavior.AllowGet);
            }
            var deployment = await _db.Deployments.FirstOrDefaultAsync();
            if (deployment != null)
            {
                using (var wamlClient = new DeploymentManager(Session.GetAccessToken(ResourceSelectors.RDFE), deployment.SubscriptionSelection))
                {
                    try
                    {
                        var nameCheck = await wamlClient.CheckServiceNameAvailableAsync(model.ClusterNameToCreate);
                        if (nameCheck.Item1)
                        {
                            return Json(true, JsonRequestBehavior.AllowGet);
                        }
                        return Json(String.Format("The cluster: {0} is invalid. {1}", model.ClusterNameToCreate, nameCheck.Item2), JsonRequestBehavior.AllowGet);
                    }
                    catch
                    {
                        return Json(String.Format("The cluster: {0} is invalid.", model.ClusterNameToCreate), JsonRequestBehavior.AllowGet);
                    }
                }
            }
            return Json("Gateway service has not been deployed to a Microsoft Azure subscription.", JsonRequestBehavior.AllowGet);
        }

        [HttpGet]
        public async Task<ActionResult> GetAnalyticsStatus(int analyticsId)
        {
            var analyticsStatus = await _db.AnalyticsStatus
                .Where(status => status.AnalyticsModelId == analyticsId)
                .OrderByDescending(d => d.DateAdded)
                .ToListAsync();
            return Json(analyticsStatus, JsonRequestBehavior.AllowGet);
        }
    }
}